using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class TMCompositeText : MonoBehaviour
{
    public float WordInterval = 10f;
    public float EvaluateLen = 10f;
    public float ShowInterval = .1f;
    public float SpaceWidth = 10f;
    Dictionary<int, RectTransform> m_Roots;
    Dictionary<int, GameObject> m_Raws;
    Dictionary<int, List<TextMeshProUGUI>> m_Texts;

    public AnimationCurve ArrCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(10f, 0f));

    [HideInInspector]
    public float RowHeight;
    void Awake()
    {
        m_Roots = new Dictionary<int, RectTransform>();
        m_Roots.Add(1, transform.Find("TitleShadowBottom").GetComponent<RectTransform>());
        m_Roots.Add(2, transform.Find("TitleShadowTop").GetComponent<RectTransform>());
        m_Roots.Add(3, transform.Find("TitleText").GetComponent<RectTransform>());
        //m_Roots.Add(4, transform.Find("TitleShadowTop").GetComponent<RectTransform>());

        m_Raws = new Dictionary<int, GameObject>();
        m_Raws.Add(1, transform.Find("TitleShadowBottom/Text").gameObject);
        m_Raws.Add(2, transform.Find("TitleShadowTop/Text").gameObject);
        m_Raws.Add(3, transform.Find("TitleText/Text").gameObject);
        //m_Raws.Add(4, gameObject.Find("TitleShadowTop/Text"));

        foreach (var obj in m_Raws)
            obj.Value.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void SetText(string text)
    {
        GameObject r = m_Raws[1];
        Transform root = m_Roots[1];
        m_Texts = new Dictionary<int, List<TextMeshProUGUI>>();
        List<TextMeshProUGUI> ts = new List<TextMeshProUGUI>();
        int word_index = 0;
        Dictionary<int, int> space_counts = new Dictionary<int, int>();
        foreach (var t in text)
        {
            if (t == ' ')
            {
                if (!space_counts.ContainsKey(word_index))
                    space_counts[word_index] = 0;

                space_counts[word_index] += 1;
                continue;
            }

            GameObject go = GameObject.Instantiate(r, root);
            go.SetActive(true);

            var tp = go.GetComponent<TextMeshProUGUI>();
            tp.text = (t.ToString());
            ts.Add(tp);
            RowHeight = tp.preferredHeight;
            word_index++;
            //($"{t} width {tp.TextRaw.preferredWidth} height {tp.TextRaw.preferredHeight}").Log(ColorOfLog.magenta);            
        }
        m_Texts.Add(1, ts);

        float arr_width = 0f;
        for (int i = 0; i < ts.Count; i++)
        {
            if (i == 0 || i == ts.Count - 1)
            {
                arr_width += ts[i].preferredWidth / 2;
            }
            else
            {
                arr_width += ts[i].preferredWidth;
            }

            if (space_counts.ContainsKey(i))
            {
                arr_width += space_counts[i] * SpaceWidth;
            }

            if (i != ts.Count - 1)
            {
                arr_width += WordInterval;
            }
        }

        Dictionary<int, Vector2> org_put = new Dictionary<int, Vector2>();

        float start_w = -arr_width / 2f;
        for (int i = 0; i < ts.Count; i++)
        {
            if (i > 0)
            {
                start_w += ts[i].preferredWidth / 2;
            }

            if (space_counts.ContainsKey(i))
                start_w += space_counts[i] * SpaceWidth;

            float vr = (float)i / (ts.Count - 1);
            float vh = ArrCurve.Evaluate(vr * EvaluateLen);

            Vector2 ap = new Vector2(start_w, vh * arr_width);
            org_put[i] = ap;
            ts[i].GetComponent<RectTransform>().anchoredPosition += ap;
            float step = vr < .5f ? .0001f : -.0001f;
            float vhs = ArrCurve.Evaluate((vr + step) * EvaluateLen);


            if (vr < .5f)
            {
                float angle = Mathf.Atan((vhs - vh) / step) * Mathf.Rad2Deg;
                //angle.ToString().Log();
                ts[i].GetComponent<RectTransform>().eulerAngles = new Vector3(0f, 0f, (angle));
            }
            else
            {
                float angle = Mathf.Atan(-(vhs - vh) / step) * Mathf.Rad2Deg;
                //angle.ToString().Log();
                ts[i].GetComponent<RectTransform>().eulerAngles = new Vector3(0f, 0f, (-angle));
            }


            start_w += ts[i].preferredWidth / 2 + WordInterval;
        }

        for (int i = 2; i <= m_Roots.Count; i++)
        {
            r = m_Raws[i];
            root = m_Roots[i];
            ts = new List<TextMeshProUGUI>();
            for (int oi = 0; oi < m_Texts[1].Count; oi++)
            {
                GameObject go = GameObject.Instantiate(r, root);
                go.SetActive(true);

                var tp = go.GetComponent<TextMeshProUGUI>();
                tp.text = (m_Texts[1][oi].text);
                ts.Add(tp);

                var gr = go.GetComponent<RectTransform>();
                var or = m_Texts[1][oi].GetComponent<RectTransform>();
                gr.anchoredPosition += org_put[oi];
                gr.eulerAngles = or.eulerAngles;
            }
            m_Texts.Add(i, ts);
        }
    }

    public void Show(System.Action cb)
    {
        StartCoroutine(_Show(cb));
    }

    IEnumerator _Show(System.Action cb)
    {
        for (int i = 0; i < m_Texts[1].Count; i++)
        {

            for (int j = 1; j <= m_Roots.Count; j++)
            {
                m_Texts[j][i].GetComponent<Animator>().Play("Appear");
            }
            yield return new WaitForSeconds(ShowInterval);
        }

        cb?.Invoke();
    }
}
